// From Network Programming for Microsoft Windows, Second Edition by 
// Anthony Jones and James Ohlund.  
// Copyright 2002.   Reproduced by permission of Microsoft Press.  
// All rights reserved.
//
//
// Common routines for resolving addresses and hostnames
//
// Files:
//      resolve.cpp     - Common routines
//      resolve.h       - Header file for common routines
//
// Description:
//      This file contains common name resolution and name printing
//      routines and is used by many of the samples on this CD.
//
// Compile:
//      See ping.cpp
//
// Usage:
//      See ping.cpp
//
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <TChar.h>

#include "resolve.h"

//
// Function: SockAddrToString
// --------------------------
//
// Description:
//    This routine is logically similar to inet_ntoa and inet_ntop, but provides
//    support for Windows XP.
//
LPTSTR
SockAddrToString(
   __in LPSOCKADDR lpsaAddress
   )
{
   static TCHAR   StringBuf[2][64];
   static int     WhichBuf = 0;
   INT            rc;
   DWORD          AddrStringLen = sizeof(StringBuf)/sizeof(TCHAR);

   rc = WSAAddressToString(
         lpsaAddress,
         lpsaAddress->sa_family == AF_INET ? sizeof(SOCKADDR_IN) : sizeof(SOCKADDR_IN6),
         NULL,                // ProtocolInfo
         StringBuf[WhichBuf & 1],
         &AddrStringLen
         );

   if( rc != 0 )
   {
      _stprintf_s(
         StringBuf[WhichBuf & 1],
         sizeof(StringBuf)/sizeof(TCHAR),
         _T("Unknown")
         );
   }

   return StringBuf[WhichBuf++ & 1];
}

//
// Function: ResolveAddress
//
// Description:
//    This routine resolves the specified address and returns a list of addrinfo
//    structure containing SOCKADDR structures representing the resolved addresses.
//    Note that if 'addr' is non-NULL, then getaddrinfo will resolve it whether
//    it is a string listeral address or a hostname.
//
struct addrinfo *ResolveAddress(char *addr, char *port, int af, int type, int proto)
{
    struct addrinfo hints,
    *res = NULL;
    int             rc;

    memset(&hints, 0, sizeof(hints));
    hints.ai_flags  = ((addr) ? 0 : AI_PASSIVE);
    hints.ai_family = af;
    hints.ai_socktype = type;
    hints.ai_protocol = proto;

    rc = getaddrinfo(
            addr,
            port,
           &hints,
           &res
            );
    if (rc != 0)
    {
        fprintf(stderr, "Invalid address %s, getaddrinfo failed: %d\n", addr, rc);
        return NULL;
    }
    return res;
}

